{% extends "helios/templates/cryptobase.html" %}

{% block content %}
<script language="javascript">

$(document).ready(function() {
    $('#result_div').hide();
    $('#waiting_div').hide();
    $('#waiting_submit_div').hide();
    $('#done_div').hide();
    $('#error_div').hide();
    
    BigInt.setup(function() {
        ELECTION_JSON = {{election.toJSON|safe}};
        ELECTION_PK = ElGamal.PublicKey.fromJSONObject(ELECTION_JSON['public_key']);
        TALLY = HELIOS.Tally.fromJSONObject({{election.encrypted_tally.toJSON|safe}}, ELECTION_PK);   
        $('#sk_section').show();
    });
});


function decrypt_and_prove_tally(tally, public_key, secret_key) {
    // we need to keep track of the values of g^{voter_num} for decryption
    var DISCRETE_LOGS = {};
    var CURRENT_EXP = 0;
    var CURRENT_RESULT = BigInt.ONE;
    DISCRETE_LOGS[CURRENT_RESULT.toString()] = CURRENT_EXP;
    
    // go through the num_tallied
    while (CURRENT_EXP < tally.num_tallied) {
      CURRENT_EXP += 1;
      CURRENT_RESULT = CURRENT_RESULT.multiply(public_key.g).mod(public_key.p);
      DISCRETE_LOGS[CURRENT_RESULT.toString()] = CURRENT_EXP;      
    }
    
    // initialize the arrays
    var decryption_factors= [];
    var decryption_proofs= [];
    
    // decrypt the tallies
    $(tally.tally).each(function(q_num, q_tally) {
        decryption_factors[q_num] = [];
        decryption_proofs[q_num] = [];

        $(q_tally).each(function(choice_num, choice_tally) {
           var one_choice_result = secret_key.decryptionFactorAndProof(choice_tally, ElGamal.fiatshamir_challenge_generator);
           
           decryption_factors[q_num][choice_num] = one_choice_result.decryption_factor
           decryption_proofs[q_num][choice_num] = one_choice_result.decryption_proof;
        });
    });
    
    return {'decryption_factors': decryption_factors, 'decryption_proofs' : decryption_proofs};
}

function get_secret_key() {
  return ElGamal.SecretKey.fromJSONObject($.secureEvalJSON($('#sk_textarea').val()));
}

function do_tally() {
  $('#sk_section').hide();
  $('#waiting_div').show();
  
  var secret_key = get_secret_key();
  
  var factors_and_proof = decrypt_and_prove_tally(TALLY, ELECTION_PK, secret_key);
  
  // json'ify it
  var factors = factors_and_proof.decryption_factors
  var decryption_proofs = $(factors_and_proof.decryption_proofs).map(function(i, q_proof) {
      return $(q_proof).map(function(j, a_proof){
         return a_proof.toJSONObject(); 
      });
  });
  
  var factors_and_proofs = {'decryption_factors': factors, 'decryption_proofs': decryption_proofs};
  var factors_and_proofs_json = $.toJSON(factors_and_proofs);
  
  // clear stuff
  secret_key = null;
  $('#sk_textarea').val("");
  
  // display the result in a text area.
  $('#waiting_div').hide();
  
  $('#result_textarea').html(factors_and_proofs_json);
  $('#result_div').show();
  $('#first-step-success').show();
}

function submit_result() {
  $('#result_div').hide();
  $('#waiting_submit_div').show();

  var result = $('#result_textarea').val();
  
  // do the post
  $.ajax({
      type: 'POST',
      url: "./upload-decryption",
      data: {'factors_and_proofs': result},
      success: function(result) {
        $('#waiting_submit_div').hide();
        if (result != "FAILURE") {
          $('#done_div').show();
        } else {
          alert('verification failed, you probably used the wrong key.');
          reset();
        }
      },
      error: function(error) {
          $('#waiting_submit_div').hide();
          $('#error_div').show();
      }
  });
}

function skip_to_second_step() {
  $('#sk_section').hide();
  $('#result_div').show();
  $('#result_textarea').html('');
  $('#skip_to_second_step_instructions').hide();
}

function reset() {
  $('#result_div').hide();
  $('#skip_to_second_step_instructions').show();
  $('#sk_section').show();
  $('#result_textarea').html('');
  $('#first-step-success').hide();
}

</script>
  <h2 class="title">Trustee {{trustee.name}} &mdash; Decrypt Result for {{election.name}}</h2>

<p>
    <b>Trustee:</b> <tt>{{trustee.email}}</tt><br />
    <b>Public Key Fingerprint:</b> <tt>{{trustee.public_key_hash}}</tt><br />
    <b>Encrypted Tally Fingerprint:</b> <tt>{{election.encrypted_tally_hash}}</tt>
</p>

    <p>
      The encrypted tally for your election has been computed.<br />
      Now it's time to compute and submit your partial decryption.
    </p>

    <p>
      This process is performed in two steps.<br /><br />
      <u>First</u>, your secret key is used to decrypt the tally <em>inside</em> your browser, without connecting to the network.<br />
      You can choose to take your browser "offline" for this step, if you'd like.<br /><br />
      <u>Second</u>, once your decryption factors have been computed, your browser will need to be "online" to submit them to the server.<br />
      If you'd like, you can compute your decryption factors, copy them to your clipboard, restart your browser, and<br />
      skip to the second step so that your browser is never online when you enter your secret key.
    </p>
    
  <div id="sk_section" style="display:none;">

      <form onsubmit="return false;">
          <h3>FIRST STEP: enter your secret key</h3>
          <textarea id="sk_textarea" cols="60" rows="5" style="height: 25em;"></textarea>
      </form>
      <p id="tally_section">
          <button onclick="do_tally();">Generate partial decryption</button>
      </p>

      <p id="skip_to_second_step_instructions">
        <a href="javascript:skip_to_second_step();">skip to the second step</a><br />
        (you need to have already computed your decryption factors.)
      </p>
  </div>
  
  <div id="waiting_div">
      Generating partial decryption factors and proofs...<br />
      <img src="/static/helios/loading.gif" />
  </div>

  <div id="waiting_submit_div">
      Submitting and checking your decryption factors and proofs...<br />
      <img src="/static/helios/loading.gif" />
  </div>
  
  <div id="result_div">
      <h3>SECOND STEP: upload your partial decryption</h3>
      <p id="first-step-success" style="display: none;">
          Your partial decryption factors and proofs have been generated below.<br />
          Your secret key has been cleared from memory.<br />
          When you're ready, you can submit this result to the server.
      </p>
      Your partial decryption:<br />
      <p>
          <textarea id="result_textarea" cols="60" rows="5" wrap="soft" style="height: 25em;"></textarea>
          <button onclick="submit_result();">Upload decryption factors to server</button>
      </p>
      <p><a href="javascript:reset()">reset and restart decryption process</a></p>
  </div>
  
  <div id="done_div">
      Done! <a href="{% url "election@view" election.uuid %}">Back to election</a>
  </div>
  
  <div id="error_div">
      Error: your secret key was likely incorrect.
  </div>

  <div id="applet_div">
  </div>

{% endblock %}
